package main.java.com.amanda.suafa;

import edu.princeton.cs.algs4.Bag;
import edu.princeton.cs.algs4.StdOut;
import main.java.com.amanda.utils.Digraph;

import java.util.Scanner;

/**
 * @author amanda
 * @Description 算法4.4 有向图的可达性
 */
public class DirectedDFS {
    private boolean[] marked;
    private int count;

    public DirectedDFS(Digraph G, int s) {
        marked = new boolean[G.V()];
        validateVertex(s);
        dfs(G, s);
    }

    public DirectedDFS(Digraph G, Iterable<Integer> sources) {
        marked = new boolean[G.V()];
        validateVertices(sources);
        for (int v : sources) {
            if (!marked[v]) dfs(G, v);
        }
    }

    private void dfs(Digraph G, int v) {
        count++;
        marked[v] = true;
        for (int w : G.adj(v)) {
            if (!marked[w]) dfs(G, w);
        }
    }

    public boolean marked(int v) {
        validateVertex(v);
        return marked[v];
    }

    public int count() {
        return count;
    }

    private void validateVertex(int v) {
        int V = marked.length;
        if (v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
    }

    private void validateVertices(Iterable<Integer> vertices) {
        if (vertices == null) {
            throw new IllegalArgumentException("argument is null");
        }
        int V = marked.length;
        int count = 0;
        for (Integer v : vertices) {
            count++;
            if (v == null) {
                throw new IllegalArgumentException("vertex is null");
            }
            validateVertex(v);
        }
        if (count == 0) {
            throw new IllegalArgumentException("zero vertices");
        }
    }

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        Digraph G = new Digraph(scanner);

        String str = scanner.nextLine();
        String[] s1 = str.split(" ");

        Bag<Integer> sources = new Bag<Integer>();
        for (int i = 1; i < s1.length; i++) {
            int s = Integer.parseInt(s1[i]);
            sources.add(s);
        }

        DirectedDFS dfs = new DirectedDFS(G, sources);
        StdOut.println("可达顶点：");
        for (int v = 0; v < G.V(); v++) {
            if (dfs.marked(v))
                StdOut.print(v + " ");
        }
        StdOut.println();
    }

}
/*
13 22
4 2 2 3 3 2 6 0 0 1 2 0 11 12 12 9 9 10 9 11 8 9 10 12 11 4 4 3 3 5 7 8 8 7 5 4 0 5 6 4 6 9 7 6 1 2 6
可达顶点：
0 1 2 3 4 5 6 9 10 11 12
 */
